package com.zym.init.log;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.http.ResponseEntity;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;

/**
 * 打印请求日志
 *
 * @author ZouYangMing
 */
@Slf4j
@Aspect
@Order(HIGHEST_PRECEDENCE)
public class RequestLog {
    // 定义切点，匹配com包及其子包下所有Controller的公共方法
    @Pointcut("execution(public * com..controller..*.*(..))*")
    public void anyController() {
    }

    // 环绕通知，在切点方法执行前后执行代码
    @Around("anyController()")
    private Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 请求URL
        Object result = null;
        long startTime = System.currentTimeMillis();
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // 类路径URL
        String packagePath = methodSignature.getDeclaringTypeName();
        // 方法名
        String packageName = methodSignature.getMethod().getName();
        try {
            // 如果不是BaseController的方法，则记录请求方法
            if (!packagePath.contains("BaseController")) {
                requestURI();
                // 打印请求方法信息
                log.debug("请求方法[{}.{}]", packagePath, packageName);
            }
            result = joinPoint.proceed();
        } finally {
            // 处理方法的返回结果
            Object myResult = result;
            if (result == null) {
                myResult = "void";
            }
            if (result instanceof byte[]) {
                myResult = "byte[]";
            }
            if (result instanceof ResponseEntity) {
                myResult = "ResponseEntity";
            }
            // 如果不是BaseController的方法，则记录耗时和响应结果
            if (!packagePath.contains("BaseController")) {
                try {
                    // 转换返回结果为JSON字符串并且限制字符长度为3000
                    String resultStr = JSONObject.toJSONString(myResult);
                    log.debug("耗时[{}ms] 响应结果[{}]", System.currentTimeMillis() - startTime, StrUtil.sub(resultStr, 0, 3000));
                } catch (Exception e) {
                    // 打印异常信息
                    log.error("打印请求日志出错:", e);
                }
            }
        }
        return result;
    }

    /**
     * 打印请求URL
     */
    private void requestURI() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = null;
        if (requestAttributes != null) {
            // 获取当前请求
            request = requestAttributes.getRequest();
        }
        String requestURL = null;
        if (request != null) {
            requestURL = request.getRequestURI();
        }
        String method = null;
        if (request != null) {
            method = request.getMethod();
        }
        // 打印请求方式和请求URL
        log.debug("请求方式[{}] 请求URL[{}]", method, requestURL);
        if (request != null && request.getParameterMap() != null) {
            // 打印请求参数
            log.debug("请求参数[{}]", JSONObject.toJSONString(request.getParameterMap()));
        }
    }

}
